package autoFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * rest
 */

/**
 * @author zhangjunfei
 * @date 2022/10/27 15:39
 * 自动生成文件
 * https://www.yuque.com/zhangjunfei-zhbui/piuuon/aivhlt
 */
public class AutoFile implements Runnable {

    private String filePath;
    private Long fileSize;

    static Random random = new Random();

    public AutoFile(String filePath, Long fileSize) {
        this.filePath = filePath;
        this.fileSize = fileSize;
    }

    @Override
    public void run() {
        String fileName = "auto-test" + Math.random();
        File f = new File(filePath, fileName);
        if (!f.exists()) {
            try {
                createFile(f, fileSize/2);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void createFile(File file, long length) throws IOException {

        FileOutputStream fos = null;
        FileChannel output = null;
        try {
            fos = new FileOutputStream(file);
            output = fos.getChannel();
            output.write(ByteBuffer.wrap(random((int) length,0,0,true,true,null,random).getBytes(StandardCharsets.UTF_8)), length - 1);
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 空文件生成方式
        // RandomAccessFile ff = null;
        // try {
        //     ff = new RandomAccessFile(file, "rw");
        //     ff.writeChars();
        //     ff.writeLength(length);
        // } finally {
        //     if (ff != null) {
        //         try {
        //             ff.close();
        //         } catch (Exception e) {
        //             e.printStackTrace();
        //         }
        //     }
        // }
    }



    public static String random(int count, int start, int end, boolean letters, boolean numbers,
                                char[] chars, Random random) {
        if (count == 0) {
            return "";
        } else if (count < 0) {
            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
        }
        if ((start == 0) && (end == 0)) {
            end = 'z' + 1;
            start = ' ';
            if (!letters && !numbers) {
                start = 0;
                end = Integer.MAX_VALUE;
            }
        }

        char[] buffer = new char[count];
        int gap = end - start;

        while (count-- != 0) {
            char ch;
            if (chars == null) {
                ch = (char) (random.nextInt(gap) + start);
            } else {
                ch = chars[random.nextInt(gap) + start];
            }
            if ((letters && Character.isLetter(ch))
                    || (numbers && Character.isDigit(ch))
                    || (!letters && !numbers))
            {
                if(ch >= 56320 && ch <= 57343) {
                    if(count == 0) {
                        count++;
                    } else {
                        // low surrogate, insert high surrogate after putting it in
                        buffer[count] = ch;
                        count--;
                        buffer[count] = (char) (55296 + random.nextInt(128));
                    }
                } else if(ch >= 55296 && ch <= 56191) {
                    if(count == 0) {
                        count++;
                    } else {
                        // high surrogate, insert low surrogate before putting it in
                        buffer[count] = (char) (56320 + random.nextInt(128));
                        count--;
                        buffer[count] = ch;
                    }
                } else if(ch >= 56192 && ch <= 56319) {
                    // private high surrogate, no effing clue, so skip it
                    count++;
                } else {
                    buffer[count] = ch;
                }
            } else {
                count++;
            }
        }
        return new String(buffer);
    }

    public static void main(String[] args) {
        Long curr = 0L;
        Long max = 1024 * 1024L*1024*1024;
        long start = System.currentTimeMillis();
        String filePath = "autottemp";
        ExecutorService executorService = Executors.newFixedThreadPool(32);
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        while (curr < max) {
            int random = (int) (Math.random() * 500 + 200);
            long fileSize = random * 1024L;
            curr += fileSize;
            executorService.submit(new AutoFile(filePath,fileSize));
        }

        executorService.shutdown();
        while(true) {
            if(executorService.isTerminated()) {
                System.out.println(System.currentTimeMillis() - start);
                break;
            }
        }

    }


}

